package com.example.security.config;

import com.example.security.hadle.AccessDeniedParmaterHandler;
import com.example.security.hadle.AuthenticationEntryPointHandler;
import com.example.security.hadle.LogoutOnSuccessHandler;
import com.example.security.realm.AdminAuthenticationProvider;
import com.example.security.realm.ComAuthenticationProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import java.util.Arrays;


/**
 * secrity配置
 *
 */

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, jsr250Enabled = true)
public class SecrityConfig extends WebSecurityConfigurerAdapter {


    @Override
    protected void configure(HttpSecurity http) throws Exception {
       // CRSF禁用，因为不使用session
        http.csrf().disable();
        // 认证失败处理类
        http.exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPointHandler()).and();
        /* 权限不足(没有赋予角色) 处理 */
        http.exceptionHandling().accessDeniedHandler(new AccessDeniedParmaterHandler()).and();
        // 基于token，所以不需要session
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and();
        http
                // 过滤请求
                .authorizeRequests()
                // 对于登录login 验证码captchaImage 允许匿名访问
                .antMatchers("/login").anonymous()
                .antMatchers("/swagger-ui.html").anonymous()
                .antMatchers("/swagger-resources/**").anonymous()
                .antMatchers("/webjars/**").anonymous()
                .antMatchers("/*/api-docs").anonymous()
                .antMatchers("/druid/**").anonymous()
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated().and();

          http.headers().frameOptions().disable();
          //退出
        http.logout().logoutUrl("/logout").logoutSuccessHandler(new LogoutOnSuccessHandler());
        // 添加JWT filter
//        http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(new UserDetailsService() {
            public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                return null;
            }
        }).passwordEncoder(new BCryptPasswordEncoder());
//        auth.authenticationProvider(new AdminAuthenticationProvider());


    }


    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        ProviderManager authenticationManager = new ProviderManager(Arrays.asList(new AdminAuthenticationProvider(),new ComAuthenticationProvider()));
            //不擦除认证密码，擦除会导致TokenBasedRememberMeServices因为找不到Credentials再调用UserDetailsService而抛出UsernameNotFoundException
             authenticationManager.setEraseCredentialsAfterAuthentication(false);
       return authenticationManager;
    }
}
